---
layout: example
categories: example/v1.0.0
version: v1.0.0
title: Sync maps with antipodes
description: Create maps that show each others antipodes. Inspired by <a href='http://www.freemaptools.com/tunnel-to-other-side-of-the-earth.htm'>tunnel to the other side of the earth</a>.
tags:
  - ui
---

<div id='map1'></div>
<div id='map2'></div>
<style>
  #map1 { position:absolute; top:0; bottom:0; left:0; right:50%; }
  #map2 { position:absolute; top:0; bottom:0; left:50%; right:0; }
</style>
<script>
// Instead of our usual one map, we will create two in this example to make
// things interesting.
var map1 = L.mapbox.map('map1', 'mapbox.streets')
    .setView([40, -74.50], 9);
var map2 = L.mapbox.map('map2', 'mapbox.emerald')
    .setView([-40, -74.50 - 180], 9);

// when either map finishes moving, trigger an update on the other one.
map1.on('moveend', follow).on('zoomend', follow);
map2.on('moveend', follow).on('zoomend', follow);

// quiet is a cheap and dirty way of avoiding a problem in which one map
// syncing to another leads to the other map syncing to it, and so on
// ad infinitum. this says that while we are calling sync, do not try to 
// loop again and sync other maps
var quiet = false;
function follow(e) {
    if (quiet) return;
    quiet = true;
    if (e.target === map1) sync(map2, e);
    if (e.target === map2) sync(map1, e);
    quiet = false;
}

// sync simply steals the settings from the moved map (e.target)
// and applies them to the other map.
function sync(map, e) {
    map.setView(antipodeCenter(e.target.getCenter()), e.target.getZoom(), {
        animate: false,
        reset: true
    });
}

// calculate the antipode of a point on earth
// http://www.trails.com/how_5125_calculate-antipode.html
function antipodeCenter(latlng) {
    return L.latLng(-latlng.lat, latlng.lng - 180).wrap();
}
</script>
